package top.v5it.logback.push.client;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;

import java.lang.reflect.Method;
import java.util.Optional;

/**
 * {@link ErrorOutput}解析，解析后并输出error日志
 *
 * @author zhanpu
 * @date 2022/9/28
 * @see ErrorOutput
 */
@Slf4j
@Aspect
public class ErrorOutputParser extends AbstractParser {

    /**
     * 定义切入点，以带有{@link ErrorOutput}注解的方法作为切入点
     */
    @Pointcut("@annotation(top.v5it.logback.push.client.ErrorOutput)")
    public void errorOutputPointCut() {
    }

    /**
     * 拦截异常操作
     *
     * @param joinPoint 切点
     * @param e         异常
     */
    @AfterThrowing(value = "errorOutputPointCut()", throwing = "e")
    public void doAfterThrowing(JoinPoint joinPoint, Exception e) {
        outputProcessor(joinPoint, e);
    }


    /**
     * 是否存在注解，如果存在就获取
     *
     * @param joinPoint 切点
     * @param e         异常
     * @return {@link ErrorOutput}
     */
    @Override
    Optional<ErrorOutput> getErrorOutput(JoinPoint joinPoint, Exception e) {
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();
        return Optional
                .ofNullable(method)
                .filter(v -> v.isAnnotationPresent(ErrorOutput.class))
                .map(v -> v.getAnnotation(ErrorOutput.class))
                .filter(v -> TEST_ERROR.test(v, e));
    }
}
